iT邦幫忙

2

筆記- 從零開始在Gitlab上執行CI/CD - Laravel9 & php8.0

  • 分享至 

  • xImage
  •  

從零開始在Gitlab上執行CI/CD

主要參考 Test and deploy Laravel applications with GitLab CI/CD and Envoy ,因為這篇文章的順序跟說明都很容易讓人做到懷疑人生,所以本篇文章會稍微修改一下順序及內容,建議閱讀本文章的同時可以邊參考原文。

  • CI(Continuous integration): 持續整合 => 自動測試
  • CD(Continuous Deployment): 持續部署 => 自動部署

目錄

[TOC]


1. 建立專案

1-1. 建立專案與測試

Laravel 專案建立後應該都會內建一兩個範例測試,可以透過指令查看這些測試結果。

php artisan test

結果:


  PASS  Tests\Unit\ExampleTest
  ✓ that true is true

  PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response

  Tests:  2 passed
  Time:   0.83s

1-2. 將專案 push 至 Gitlab

# 命令中的專案位置記得改成你的專案

cd laravel-sample
git init
git remote add origin git@gitlab.example.com:<USERNAME>/laravel-sample.git
git add .
git commit -m 'Initial Commit'
git push -u origin main

2. 設定要部署的伺服器

2-1. 建立用來部署的 user

官方範例是使用 ACL 這個套件來管理權限,所以我們也裝一下。

sudo apt install acl

裝好後就建立使用者

# Create user deployer
sudo adduser deployer
# Give the read-write-execute permissions to deployer user for directory /var/www
sudo setfacl -R -m u:deployer:rwx /var/www

2-2. 用這個使用者建立 SSH Key

要先切換至這個使用者,並用 deployer 的身份建立 SSH Key

# 切換使用者
sudo su deployer

切換後就可以建立 Key 了,建立時⚠️記得不要設置密碼⚠️

ssh-keygen -t rsa -b 2048

之後使用指令將公鑰複製到 /authorized_keys

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

並複製 私鑰 並貼到 Gitlab Repo > Settings > CI/CD > Variables

# 顯示私鑰
cat ~/.ssh/id_rsa

同時也要將 公鑰 複製並貼到 Gitlab Repo > Settings > Repository > Deploy Key。頁面上的 Title 隨便填就好

# 顯示公鑰
cat ~/.ssh/id_rsa.pub

以上步驟完成後可以試著 clone 專案看看權限是否設置正常

# 命令中的專案位置記得改成你的專案
git clone git@gitlab.example.com:<USERNAME>/laravel-sample.

如果有顯示 Are you sure you want to continue connecting (yes/no)? 請輸入 yes


3. 建立 Gitlab CI 環境

這一步要回來我們自己的電腦上面做。照著原文件的做法,會透過 Docker 來做。中間需要在自己機器上 build 過一次,所以本機也會需要安裝 Docker。

原文的版本比較舊,裡面提到的一些設置位置會跟現在 Gitlab 上看到的不同。包含原文說要先開權限,現在版本則預設就已經開好了。

*要部署的伺服器不需要裝 Docker。

3-1. 建立 Container Image

原文件是使用 php 7.4 ,但我們專案為 Laravel 9 & php 8.0。有些舊版本套件在 php 8.0 已經無法使用,因此 Dockerfile 的內容會跟原文不同。

在專案根目錄建立 Dockerfile 檔案

# Set the base image for subsequent instructions
FROM php:8.0

# Update packages
RUN apt-get update

# Install PHP and composer dependencies
RUN apt-get install -qq git curl libmcrypt-dev libjpeg-dev libpng-dev libfreetype6-dev libbz2-dev libzip-dev

# Clear out the local repository of retrieved package files
RUN apt-get clean

# Install needed extensions
# Here you can install any other extension that you need during the test and deployment process
RUN docker-php-ext-install pdo_mysql zip

# Install Composer
RUN curl --silent --show-error "https://getcomposer.org/installer" | php -- --install-dir=/usr/local/bin --filename=composer

# Install Laravel Envoy
RUN composer global require "laravel/envoy" --dev

建立完成後需將 docker 登入至 GitLab registry,輸入完指令會需要輸入你的 Gitlab 帳號密碼。

docker login registry.gitlab.com

之後就能 buildpush 映像檔到 Gitlab 上

# 命令中的專案位置記得改成你的專案
docker build -t registry.gitlab.com/<USERNAME>/laravel-sample .

docker push registry.gitlab.com/<USERNAME>/laravel-sample

完成後可以到 Gitlab Repo > Package and registries > Container Registry 找到剛剛 push 上去的 image


4. 設定 .gitlab-ci.yml

在根目錄建立 .gitlab-ci.yml ,這是讓 gitlab 自動運行 CI/CD 的關鍵檔案。設定好後 gitlab 就會將這個檔案的指令丟給上面步驟做的 Docker 去做執行,一切的測試跟部署的調用都會透過 Docker。

與 php 版本一樣,這邊也因應現今版本做了稍微的修改。

image: registry.gitlab.com/<USERNAME>/laravel-sample:latest

services:
  - mysql:latest

variables:
  MYSQL_DATABASE: homestead
  MYSQL_ROOT_PASSWORD: secret
  DB_HOST: mysql
  DB_USERNAME: root

stages:
  - test
  - deploy

unit_test:
  stage: test
  script:
    - cp .env.example .env
    - composer install
    - php artisan key:generate
    - php artisan migrate
    - php artisan test

deploy_production:
  stage: deploy
  script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

    - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
  environment:
    name: production
    url: https://example.com
  when: manual
  only:
    - master

下面幾個小節將會把 .gitlab-ci.yml 中的區塊拆出來解說。

4-1. SQL變數

這裡的 SQL 變數是給 Docker 設定預設的資料庫名稱、及帳號密碼,所以這部分我們可以不用動它。

# .gitlab-ci.yml

variables:
  MYSQL_DATABASE: homestead
  MYSQL_ROOT_PASSWORD: secret
  DB_HOST: mysql
  DB_USERNAME: root

因為測試的指令會執行 cp .env.example .env 將範例的環境變數當成正式的環境變數來用。 所以要改的是我們的 .env.example 中的資料庫設定,只要改成跟上面一樣就可以了。

# .env.example

DB_CONNECTION=mysql
DB_HOST=0.0.0.0
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=root
DB_PASSWORD=secret

4-2. 單元測試

unit_test:
  script:
    # 安裝 composer 的套件
    - composer install
    # 設置 .env
    - cp .env.example .env
    # 產生 environment key
    - php artisan key:generate
    # 執行 migrations
    - php artisan migrate
    # 執行測試
    - php artisan test

4-3. 部署

這邊的命令會透過 Envoy 去執行部署,關於 Envoy 的設定我寫在第五章。
因此這邊就看一下底下的 environmentwhenonly分別的作用。

deploy_production:
  ...
  environment:
    name: production
    url: http://192.168.1.1
  when: manual
  only:
    - main
environment:

會顯示在部署完成後 gitlab 上的 Environments 頁面 中的按鈕,分別是按鈕的 名稱(name) 及按鈕的連結(url)

when:

設定執行部署的時機, manual(手動)

only:

設定是在哪個 branch 的 commit 推上來後才能夠執行。

4-4. Commit

調整完後就將這個檔案 commit 並 push 到 gitlab 上。


5. 設置自動部署

這個步驟先在自己的機器上做,之後再用 git 推到線上就好,之後會在 docker 內去跑這段程式並部署到你的機器上。

5-1. 安裝 laravel/envoy

composer require laravel/envoy --dev

並在根目錄建立 Envoy.blade.php

@servers(['web' => 'deployer@192.168.1.1'])

@setup
    $repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git';
    $releases_dir = '/var/www/app/releases';
    $app_dir = '/var/www/app';
    $release = date('YmdHis');
    $new_release_dir = $releases_dir .'/'. $release;
@endsetup

...

記得修改裡面的內容,將 deployer@192.168.1.1 後面的 192.168.1.1 換成你要部署機器的 IP,因為前面有設定過使用者為 deployer 因此就不用改使用者名稱。

*如果要部署多台機器則將其他機器的資料加在後面就行,例如:

@servers([
  'web' => 'deployer@192.168.1.1',
  'web2' => 'deployer@192.168.1.2',
])

部署的檔案位置及資料夾可以自行調整即可。

如果沒修改的話,部署完後 /var/www/app 資料夾會有 releasesstoregecurrent 三個資料夾,並會將 app/storegeapp/.env 用 link 的方式連接到最新部署的專案資料夾內,並將最新部署的專案 link 到外面的 current 資料夾中。

注意:一開始沒有 storege 以及裡面的資料夾,需要在第一次自動部署前先手動建立,否則網頁打開找不到資料夾就會報錯。

mkdir storege/app
mkdir storage/framework/cache
mkdir storage/framework/sessions
mkdir storage/framework/views
mkdir storage/logs

完整的 script 如下

@servers(['web' => 'deployer@192.168.1.1'])

@setup
    $repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git';
    $releases_dir = '/var/www/app/releases';
    $app_dir = '/var/www/app';
    $release = date('YmdHis');
    $new_release_dir = $releases_dir .'/'. $release;
@endsetup

@story('deploy')
    clone_repository
    run_composer
    update_symlinks
@endstory

@task('clone_repository')
    echo 'Cloning repository'
    [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
    git clone --depth 1 {{ $repository }} {{ $new_release_dir }}
    cd {{ $new_release_dir }}
    git reset --hard {{ $commit }}
@endtask

@task('run_composer')
    echo "Starting deployment ({{ $release }})"
    cd {{ $new_release_dir }}
    composer install --prefer-dist --no-scripts -q -o
@endtask

@task('update_symlinks')
    echo "Linking storage directory"
    rm -rf {{ $new_release_dir }}/storage
    ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage

    echo 'Linking .env file'
    ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env

    echo 'Linking current release'
    ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current
@endtask

如果有要新增執行的指令也可以自己寫在裡面,像是 npm install 或是 npm build 等等的。

再把 Envoy.blade.php 也 commit 上去後整個流程就完成了。


小結

上面除了第二章建立使用者時會需要登入到你要部署的伺服器 其他都在自己的電腦就能完成。很多配置文件字很多看起來很雜,其實一行一行慢慢看還蠻容易讀懂的。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言